//
//  EVEAPISkillTree.m
//  EVE Mac Suite
//
//  Created by Vadim Lozko on 2/7/09.
//  Copyright 2009 __Vadim__. All rights reserved.
//

#import "EVEAPISkillTree.h"
#import "EVEAPICoreDataController.h"
#import "EVECDSkillGroup.h"
#import "EVECDSkill.h"
#import "EVECDSkillBonus.h"
#import "EVECDSkillRequirement.h"

static NSString* sRow = @"row";
static NSString* sGroupName = @"groupName";
static NSString* sTypeName = @"typeName";
static NSString* sTypeID = @"typeID";
static NSString* sSkillLevel = @"skillLevel";
static NSString* sBonusType = @"bonusType";
static NSString* sDescription = @"description";
static NSString* sRank = @"rank";
static NSString* sPrimaryAttribute = @"primaryAttribute";
static NSString* sSecondaryAttribute = @"secondaryAttribute";

@implementation EVEAPISkillTree

+(EVEAPISkillTree*)apiSkillTree
{
	static EVEAPISkillTree *apiSkillTree;
	
	@synchronized(self)
	{
		if (!apiSkillTree)
		{
			apiSkillTree = [[EVEAPISkillTree alloc] init];
		}
		return apiSkillTree;
	}
	return nil;
}

#pragma mark EVEAPIDataHandler protocol methods

-(NSString*)xmlStorePath
{
	return [[EMSGeneralUtils applicationSupportFolder] stringByAppendingPathComponent:@"SkillTree.xml"];
}

-(NSString*)APIDocumentType
{
	return SKILL_TREE_API_TYPE;
}

-(void)update
{
	[[NSNotificationCenter defaultCenter] postNotificationName:WILL_UPDATE_SKILL_TREE_NOTIFICATION_NAME object:self];
	[super update];
}

-(void)updateCoreDataStore
{
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	//[EVECDContext lock];
	//[[EVEAPICoreDataController coreDataController] performSelectorOnMainThread:@selector(lockContext) withObject:nil waitUntilDone:YES];
	NSData* xmlDocData = [xmlDoc XMLData];
	NSXMLParser* parser = [[NSXMLParser alloc] initWithData:xmlDocData];
	parser.delegate = self;
	
#ifdef DEBUG
	NSLog(@"Starting initial XML Parsing");
#endif
	_firstParseRound = YES;
	[parser parse];
	
#ifdef DEBUG
	NSLog(@"Linking Skill Requirements");
#endif
	_firstParseRound = NO;
	parser = [[NSXMLParser alloc] initWithData:xmlDocData];
	parser.delegate = self;
	[parser parse];
	
	[[EVEAPICoreDataController coreDataController] saveData];
#ifdef DEBUG
	NSLog(@"Done with Core Data Importing");
#endif		
	//[EVECDContext unlock];
	//[[EVEAPICoreDataController coreDataController] performSelectorOnMainThread:@selector(unlockContext) withObject:nil waitUntilDone:YES];
	//[self performSelectorOnMainThread:@selector(updateDidFinish:) withObject:(NSNumber*)kCFBooleanTrue waitUntilDone:NO];
	[self updateDidFinish:(NSNumber*)kCFBooleanTrue];
	[pool release];
}

-(void)verifyCoreDataStore
{
	//Do a search for skills. Any amount > 0 would be considered valid
	NSSet* verifySkillsResults = [EVECDContext fetchObjectsForEntityName:@"EVECDSkillGroup" withPredicate:nil];
	if([verifySkillsResults count] == 0)
	{
		//[NSThread detachNewThreadSelector:@selector(updateCoreDataStore) toTarget:self withObject:nil];
		[self updateCoreDataStore];
	} else {
		//skillTree = [[EVECDContext fetchObjectForEntityName:@"EVECDSkillTree" withPredicate:nil] retain];
		[self updateDidFinish:(NSNumber*)kCFBooleanTrue];
	}
}

-(BOOL)cachedDataCurrent
{
	return YES;
}

-(void)documentDidDownload:(BOOL)success;
{
	if([delegate respondsToSelector:@selector(skillTreeXMLDownloadDidFinish:)])
	{
		[delegate skillTreeXMLDownloadDidFinish:success];
	}
}

-(void) startUpdateTimer
{
	//Don't want to call upate on the skill tree
}

-(NSSet*)skillGroups
{
	return [EVECDContext fetchObjectsForEntityName:@"EVECDSkillGroup" withPredicate:nil];
}

@end

@implementation EVEAPISkillTree (ParseDelegate)

-(void)parser:(NSXMLParser*)parser 
didStartElement:(NSString*)elementName
 namespaceURI:(NSString*)namespaceURI 
qualifiedName:(NSString*)qualifiedName 
   attributes:(NSDictionary*)attributeDict
{
	//[EVECDContext lock];
	if([elementName isEqualToString:sRow])
	{
		if([attributeDict objectForKey:sGroupName])
		{
			if(_currentGroup)
			{
				[_currentGroup release];
			}
			if(_firstParseRound)
			{
#ifdef DEBUG
				NSLog(@"Creating Group item");
#endif
				_currentGroup = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDSkillGroup" 
															  inManagedObjectContext:EVECDContext] retain];
				_currentGroup.name = [attributeDict objectForKey:@"groupName"];
				_currentGroup.id = [NSNumber numberWithInt:[[attributeDict objectForKey:@"groupID"] intValue]];
			}
		}
		else if([attributeDict objectForKey:sTypeName])
		{
			if(_currentSkill)
			{
				[_currentSkill release];
			}
			if(_firstParseRound)
			{
#ifdef DEBUG
			NSLog(@"Creating Skill item");
#endif
				_currentSkill = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDSkill" 
															   inManagedObjectContext:EVECDContext]retain];
				_currentSkill.name = [attributeDict objectForKey:sTypeName];
				_currentSkill.id = [NSNumber numberWithInt:[[attributeDict objectForKey:@"typeID"] intValue]];
				_currentSkill.partOfSkillGroup = _currentGroup;
			} else {
				NSPredicate* skillIDPredicate = [NSPredicate predicateWithFormat:@"id == %@",
												 [NSNumber numberWithInt:[[attributeDict objectForKey:sTypeID] intValue]]];
				_currentSkill = [[EVECDContext fetchObjectForEntityName:@"EVECDSkill" withPredicate:skillIDPredicate] retain];
			}
		}
		else if([attributeDict objectForKey:sBonusType] && _firstParseRound)
		{
#ifdef DEBUG
			NSLog(@"Linking Skill Bonus Collection");
#endif
			EVECDSkillBonus* bonus = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDSkillBonus" 
																   inManagedObjectContext:EVECDContext];
			bonus.type = [attributeDict objectForKey:sBonusType];
			bonus.value = [NSNumber numberWithInt:[[attributeDict objectForKey:@"bonusValue"] intValue]];
			[_currentSkill addSkillBonusCollectionObject:bonus];
		}
		else if([attributeDict objectForKey:sTypeID] && [attributeDict objectForKey:sSkillLevel] && !_firstParseRound)
		{
#ifdef DEBUG
			NSLog(@"Linking Skill Requirements");
#endif
			NSNumber* typeIDAttribute = [NSNumber numberWithInt:[[attributeDict objectForKey:@"typeID"] intValue]];
			NSNumber* skillLevelAttribute = [NSNumber numberWithInt:[[attributeDict objectForKey:@"skillLevel"] intValue]];
			NSPredicate* requiredIDPredicate = [NSPredicate predicateWithFormat:@"skill.id == %@",  typeIDAttribute];
			NSPredicate* requiredLevelPredicate = [NSPredicate predicateWithFormat:@"level == %@", skillLevelAttribute];
			NSPredicate* skillRequirementPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
													  [NSArray arrayWithObjects:requiredIDPredicate, requiredLevelPredicate, nil]];
			EVECDSkillRequirement* skillRequirement = (EVECDSkillRequirement*)[EVECDContext fetchObjectForEntityName:@"EVECDSkillRequirement"
																									   withPredicate:skillRequirementPredicate];
			if(!skillRequirement)
			{
				skillRequirement = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDSkillRequirement" 
																 inManagedObjectContext:EVECDContext];
				skillRequirement.level = skillLevelAttribute;
				NSPredicate* requiredSkillPredicate = [NSPredicate predicateWithFormat:@"id == %@", typeIDAttribute];
				skillRequirement.skill = (EVECDSkill*)[EVECDContext fetchObjectForEntityName:@"EVECDSkill" withPredicate:requiredSkillPredicate];
			}
			[skillRequirement addRequiredForSkillObject:_currentSkill];
		}
	}
	self.currentCharacters = @"";
	//[EVECDContext unlock];
}

- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString*)string
{
	self.currentCharacters = [self.currentCharacters stringByAppendingString:string];
}

- (void)parser:(NSXMLParser*)parser 
 didEndElement:(NSString*)elementName
  namespaceURI:(NSString*)namespaceURI
 qualifiedName:(NSString*)qName
{
	//[EVECDContext lock];
	if([elementName isEqualToString:sDescription])
	{
		_currentSkill.skillDescription = self.currentCharacters;
	}
	else if([elementName isEqualToString:sRank])
	{
		_currentSkill.rank = [NSNumber numberWithInt:[self.currentCharacters intValue]];
	}
	else if([elementName isEqualToString:sPrimaryAttribute])
	{
		_currentSkill.primaryAttribute = self.currentCharacters;
	}
	else if([elementName isEqualToString:sSecondaryAttribute])
	{
		_currentSkill.secondaryAttribute = self.currentCharacters;
	}
	//[EVECDContext unlock];
}

-(void)parserDidEndDocument:(NSXMLParser*)parser
{
	[_currentSkill release];
	_currentSkill = nil;
	[_currentGroup release];
	_currentGroup = nil;
	[super parserDidEndDocument:parser];
}
@end
